package com.atguigu.guli.service.ucenter.service.impl;

import com.atguigu.guli.common.utils.HttpClientUtils;
import com.atguigu.guli.service.base.exception.GuliException;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.base.utils.JwtHelper;
import com.atguigu.guli.service.base.utils.JwtInfo;
import com.atguigu.guli.service.ucenter.config.WxLoginProperties;
import com.atguigu.guli.service.ucenter.entity.Member;
import com.atguigu.guli.service.ucenter.mapper.MemberMapper;
import com.atguigu.guli.service.ucenter.service.WxLoginService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Service
public class WxLoginServiceImpl implements WxLoginService {

    @Autowired
    WxLoginProperties wxLoginProperties;

    @Autowired
    MemberMapper memberMapper;

    // 用户点击微信获取微信登录二维码
    @Override
    public String login(HttpSession session) {

        try {
            String url = "https://open.weixin.qq.com/connect/qrconnect?" +
                    "appid=%s" +  //应用在wx平台注册的应用id
                    "&redirect_uri=%s" + //用户授权后的回调地址  需要进行UrlEncode
                    "&response_type=code" + //
                    "&scope=snsapi_login" +
                    "&state=%s" +
                    "#wechat_redirect";
            // wx登录 在微信平台注册的应用需要设置一个 域名，如果我们设置的redirectUri域名和 配置的不一致，则报错
            String redirectUri = wxLoginProperties.getRedirectUri();
            String state = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
            session.setAttribute("wxState",state);
            url = String.format(url ,  //将带占位符的字符串的参数设置好 并接收返回的字符串
                    wxLoginProperties.getAppId() , URLEncoder.encode(redirectUri , "UTF-8"),state
            );
            //重定向
            return "redirect:"+url;

        } catch (Exception e) {
            e.printStackTrace();
            return "redirect:http://localhost:3000/error";
        }
    }

    //2、用户授权后的回调
    @Override
    public String callback(String code, String state, HttpSession session) {

        Object wxState = session.getAttribute("wxState");
        if(!StringUtils.isEmpty(state) && state.equals(wxState)){
            try {
                //本次请求携带的state是之前的会话生成的state
                //根据code获取wx平台的 accessToken(表示哪个应用要获取code对应的wx用户信息)
                String url  = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                        "appid="+ wxLoginProperties.getAppId() +
                        "&secret=" + wxLoginProperties.getAppSecret() +
                        "&code="+ code +
                        "&grant_type=authorization_code";
                //发起网络请求根据code获取accessToken
                HttpClientUtils client = new HttpClientUtils(url);
                client.get();
                //获取请求响应的内容
                String content = client.getContent();
                Gson gson = new Gson();
                Map resultMap = gson.fromJson(content, Map.class);
                if(resultMap.get("errcode")!=null){
                    throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
                }
                String accessToken = resultMap.get("access_token").toString();
                String openid = resultMap.get("openid").toString();//wx平台 wx用户的唯一id
                System.out.println(accessToken);
                System.out.println(openid);

                //判断当前wx用户之前是否已经登录过我们的平台
                LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Member::getOpenid , openid);
                Member member = memberMapper.selectOne(queryWrapper);
                if(member==null){
                    // 用户没有登录过, 数据库中保存用户信息
                    //根据accessToken+openid获取用户的wx信息
                    url = "https://api.weixin.qq.com/sns/userinfo?" +
                            "access_token="+ accessToken +
                            "&openid="+ openid;
                    HttpClientUtils client2 = new HttpClientUtils(url);
                    client2.get();
                    content = client2.getContent();
                    resultMap = gson.fromJson(content , Map.class);
                    if(resultMap.get("errcode")!=null){
                        throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
                    }
                    String  nickname = resultMap.get("nickname").toString();
                    Integer sex  = (int)(Double.parseDouble(resultMap.get("sex").toString()));
                    String headimgurl = resultMap.get("headimgurl").toString();
                    System.out.println("content = " + content);
                    System.out.println("nickname = " + nickname);
                    System.out.println("sex = " + sex);
                    System.out.println("headimgurl = " + headimgurl);
                    //如果用户第一次使用wx登录, 将wx用户转为我们自己的用户存到本地数据库中
                    member = new Member();
                    member.setAvatar(headimgurl);
                    member.setSex(sex);
                    member.setNickname(nickname);
                    member.setOpenid(openid);
                    memberMapper.insert(member);

                }else{
                    Date date = member.getGmtModified();
//                    new DateTime(date)
                    //判断用户的wx信息在数据库中保存的时间，如果超过7天则重新查询更新数据
                    long time = System.currentTimeMillis() - new DateTime(date).getMillis(); // 当前时间 - 更新时间
                    if(time/(1000*60*60*24)>=7){
                        //根据accessToken+openid获取用户的wx信息
                        url = "https://api.weixin.qq.com/sns/userinfo?" +
                                "access_token="+ accessToken +
                                "&openid="+ openid;
                        HttpClientUtils client2 = new HttpClientUtils(url);
                        client2.get();
                        content = client2.getContent();
                        resultMap = gson.fromJson(content , Map.class);
                        if(resultMap.get("errcode")!=null){
                            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
                        }
                        String  nickname = resultMap.get("nickname").toString();
                        Integer sex  = (int)(Double.parseDouble(resultMap.get("sex").toString()));
                        String headimgurl = resultMap.get("headimgurl").toString();
                        //将wx用户转为我们自己的用户存到本地数据库中
                        member.setAvatar(headimgurl);
                        member.setSex(sex);
                        member.setNickname(nickname);
                        memberMapper.updateById(member);//更新wx用户的信息
                    }

                }
                //将wx信息转为jwt响应
                JwtInfo jwtInfo = new JwtInfo();
                jwtInfo.setId(member.getId());//数据库记录的id
                jwtInfo.setNickname(member.getNickname());
                jwtInfo.setAvatar(member.getAvatar());
                String token = JwtHelper.createToken(jwtInfo);

                //由于浏览器访问的是8160服务器进行的wx登录，如果希望现实登录成功的数据 需要跳转到3000服务器并携带token
                //只能使用重定向实现
                return "redirect:http://localhost:3000?token="+token;

            } catch (Exception e) {
                e.printStackTrace();
                //有异常时，重定向让浏览器访问错误页面
//                throw new GuliException()
            }
        }
        return "redirect:http://localhost:3000/error";

    }


}
